#ifndef _ATOMIC_H
#define _ATOMIC_H
 
/* Check GCC version, just to be safe */
#if !defined(__GNUC__) || (__GNUC__ < 4) || (__GNUC_MINOR__ < 1)
# error atomic.h works only with GCC newer than version 4.1
#endif /* GNUC >= 4.1 */
 
/**
   * Atomic type.
    */
typedef struct Atomic_t{
		volatile int counter;
}atomic_t;
 
#define ATOMIC_INIT(i)  { (i) }
 
/**
   * Read atomic variable
    * @param v pointer of type atomic_t
	 *
	  * Atomically reads the value of @v.
	   */
#define atomic_read(v) ((v)->counter)
 
/**
   * Set atomic variable
    * @param v pointer of type atomic_t
	 * @param i required value
	  */
#define atomic_set(v,i) (((v)->counter) = (i))
 
/**
   * Add to the atomic variable
    * @param i integer value to add
	 * @param v pointer of type atomic_t
	  */
static inline void atomic_add( int i, atomic_t *v )
{
		(void)__sync_add_and_fetch(&v->counter, i);
}
 
/**
   * Subtract the atomic variable
    * @param i integer value to subtract
	 * @param v pointer of type atomic_t
	  *
	   * Atomically subtracts @i from @v.
	    */
static inline void atomic_sub( int i, atomic_t *v )
{
		(void)__sync_sub_and_fetch(&v->counter, i);
}
 
/**
   * Subtract value from variable and test result
    * @param i integer value to subtract
	 * @param v pointer of type atomic_t
	  *
	   * Atomically subtracts @i from @v and returns
	    * true if the result is zero, or false for all
		 * other cases.
		  */
static inline int atomic_sub_and_test( int i, atomic_t *v )
{
		return !(__sync_sub_and_fetch(&v->counter, i));
}
 
/**
   * Increment atomic variable
    * @param v pointer of type atomic_t
	 *
	  * Atomically increments @v by 1.
	   */
static inline void atomic_inc( atomic_t *v )
{
		(void)__sync_fetch_and_add(&v->counter, 1);
}
 
/**
   * @brief decrement atomic variable
    * @param v: pointer of type atomic_t
	 *
	  * Atomically decrements @v by 1.  Note that the guaranteed
	   * useful range of an atomic_t is only 24 bits.
	    */
static inline void atomic_dec( atomic_t *v )
{
		(void)__sync_fetch_and_sub(&v->counter, 1);
}
 
/**
   * @brief Decrement and test
    * @param v pointer of type atomic_t
	 *
	  * Atomically decrements @v by 1 and
	   * returns true if the result is 0, or false for all other
	    * cases.
		 */
static inline int atomic_dec_and_test( atomic_t *v )
{
		return !(__sync_sub_and_fetch(&v->counter, 1));
}
 
/**
   * @brief Increment and test
    * @param v pointer of type atomic_t
	 *
	  * Atomically increments @v by 1
	   * and returns true if the result is zero, or false for all
	    * other cases.
		 */
static inline int atomic_inc_and_test( atomic_t *v )
{
		return !(__sync_add_and_fetch(&v->counter, 1));
}
 
/**
   * @brief add and test if negative
    * @param v pointer of type atomic_t
	 * @param i integer value to add
	  *
	   * Atomically adds @i to @v and returns true
	    * if the result is negative, or false when
		 * result is greater than or equal to zero.
		  */
static inline int atomic_add_negative( int i, atomic_t *v )
{
		return (__sync_add_and_fetch(&v->counter, i) < 0);
}
 
#endif
